//
// Created by root on 2023/1/31.
//

#include "src/server.h"
//#include "src/monotonic.h"
//#include "src/cluster.h"
//#include "src/slowlog.h"
//#include "src/bio.h"
//#include "src/latency.h"
//#include "src/atomicvar.h"
#include "src/mt19937-64.h"
//#include <time.h>
//#include <signal.h>
//#include <sys/wait.h>
//#include <errno.h>
//#include <assert.h>
//#include <ctype.h>
//#include <stdarg.h>
//#include <arpa/inet.h>
//#include <sys/stat.h>
//#include <fcntl.h>
//#include <sys/time.h>
//#include <sys/resource.h>
//#include <sys/uio.h>
//#include <sys/un.h>
//#include <limits.h>
//#include <float.h>
//#include <math.h>
//#include <sys/resource.h>
//#include <sys/utsname.h>
//#include <locale.h>
//#include <sys/socket.h>
//#include <sys/resource.h>

//#ifdef __linux__
//#include <sys/mman.h>
//
//#endif

void testSDS();
void testAlign();
void testZipList();
void testSkipList();
void testQuickList();
int testRandomLevel();
void testDict();
void scanCallbackTest();

extern struct redisServer server;
void test_thread_mutex();
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int main(int argc, char **argv) {

//    testAlign();
//    testSDS();
//    testZipList();
//    testQuickList();

//    int level = 0;
//    while (level <5) {
//        level = testRandomLevel();
//        printf("%d\n",level);
//    }
//    testSkipList();
    if(-1){
        printf("-1 is also true \n");
    }
    test_thread_mutex();
    int i = 1;
    do {
        printf("%d",i);
        i--;
    }while (i == 0);
//    testDict();
}




/**
 * __attribute__ ((__packed__))取消对齐
 *  __attribute__((aligned(4)))指定对齐大小，这里只整个结构体的对齐，当结构体内各成员间对齐后，没有达到aligned的值，则补齐
 *  https://code84.com/787223.html
 *  #pragma pack(8)  //设置结构体内成员间对齐大小，pack中参数大小与成员类型最长的值，取小值
 *  如：结构体中最大的类型是int四个字节，那么设置pragma pack(8)，实际结构体内还是按4字节来对齐，此时，c1一个字节后会补齐三个字节
 *  假如c1,c2相邻，这两个成员则合并两个字节，然后补齐两个字节，然后再到下一个成员
 *
 */
#pragma pack(2)
typedef struct __attribute__((aligned(8)))/*__attribute__ ((__packed__))*/
{
    char c1;//1字节 0   对齐：0
    int i;  //4字节 1        4
    char c2;//     5        8
    long l0;
    char arr[];
} test_0;
//#pragma pack()

void testSDS() {
//    printf("hello sds");
    char * char0= "hello sds \n";
    sds s0 = sdsnew("ddddddd");//"Xhello sds \n"
    sds s00 = sdscat(s0,"catt");//预分配机制，减少分配次数，新增后总长度 len+addlen < 1MB，则按新长度的两倍扩容,新增后总长度 len+addlen > 1MB，则按新长度加上 1MB 扩容
//    s = s-1;
    size_t size1 = sizeof(s0);
//    sdsRemoveFreeSpace(s00);//将预分配的空间收缩
    sdsclear(s00); //只是将字符串的结束标识设置到flag后，将len设置为0
    sdsfree(s00);//释放sds占用的空间

    //"\001hello sds dddddddddddddddddddddddddddddffffffffffffffffffffffffffdddddddddddddfdfddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
    sds s2 = sdsnew("hello sds dddddddddddddddddddddddddddddffffffffffffffffffffffffffdddddddddddddfdfddd");
    sds s22 = sdscat(s2,"catt");
    sdsRemoveFreeSpace(s22);
}

void testAlign(){
    //内存对齐测试
    test_0 a;
    test_0 *aa = &a;
    printf("c1 -> %d, i -> %d, c2 -> %d,l0-> %d,arr->%d\n",
           offsetof(test_0,c1),
           offsetof(test_0,i),
           offsetof(test_0,c2),
           offsetof(test_0,l0),
           offsetof(test_0,arr)
    );
    int size = sizeof(a);
    printf("c1 -> %d, i -> %d, c2 -> %d,l0-> %d,a->%d\n",
           (unsigned int)(void *)&a.c1 /*- (unsigned int)(void *)&a*/,
           (unsigned int)(void *)&a.i/*- (unsigned int)(void *)&a*/,
           (unsigned int)(void *)&a.c2 /*- (unsigned int)(void *)&a*/,
           (unsigned int)(void *)&a.l0 /*- (unsigned int)(void *)&a*/,
           (unsigned int)(void *)&a);
    printf("c1 -> %d, i -> %d, c2 -> %d\n",
           (unsigned int)(void *)&a.c1 - (unsigned int)(void *)&a,
           (unsigned int)(void *)&a.i- (unsigned int)(void *)&a,
           (unsigned int)(void *)&a.c2 - (unsigned int)(void *)&a);

    //柔性数组测试
    test_0 *softp = malloc(sizeof(test_0)+sizeof(int)*4);
    test_0 soft = *softp;
    int sizes = sizeof(soft);//sizeof不会列出柔性数组占用大小
    soft.arr[0] = 'h';
    int sizes1 = sizeof(soft);

}
void testZipList(){
    unsigned char *zl = ziplistNew();
    //头长度10，
    int headerLen = (sizeof(uint32_t)*2+sizeof(uint16_t));
    //zl+headerlen为插入位置，即index0的位置，实际是第一个entry的插入位置
    //index0再往后推两个字节位置才是hello的存放位置，index0,hello中间的两个字节分别存放prelen,encoding.
    ziplistInsert(zl,zl+headerLen,"hello",6);
    unsigned char *index0 = ziplistIndex(zl, 0);
    unsigned int len = ziplistLen(zl);

}
void testQuickList(){
    quicklist *quickList = quicklistNew(3,1);
    quicklistPushHead(quickList,"hello0",6);
    quicklistPushHead(quickList,"hello1",6);
    quicklistPushHead(quickList,"hello2",6);
    quicklistPushHead(quickList,"hello3",6);
    quicklistPushHead(quickList,"hello4",6);
    quicklistPushHead(quickList,"hello5",6);
    quicklistPushHead(quickList,"hello6",6);
    quicklistInsertAfter(quickList,quickList->tail->prev,"insert",6);
}
void testSkipList(){
    zskiplist *my_list = zslCreate();
    sds sds01 = sdsnew("0001a");
    sds sds02 = sdsnew("0002a");
    sds sds03 = sdsnew("0003a");
    sds sds04 = sdsnew("0004a");
    sds sds05 = sdsnew("0005a");
    zslInsert(my_list,1,sds01);
    zslInsert(my_list,2,sds02);
    zslInsert(my_list,3,sds03);
    zslInsert(my_list,4,sds04);
    zslInsert(my_list,5,sds05);

}
void testDict(){
    dict *dict0 = dictCreate(&hashDictType, NULL);
    dictAdd(dict0,sdsnew("0001a"),sdsnew("value1"));
    dictAdd(dict0,sdsnew("0001aa"),sdsnew("value11"));
    dictAdd(dict0,sdsnew("0002a"),sdsnew("value2"));
    dictAdd(dict0,sdsnew("0003a"),sdsnew("value3"));
    dictAdd(dict0,sdsnew("0004a"),sdsnew("value4"));
    dictAdd(dict0,sdsnew("0005a"),sdsnew("value5"));
    dictAdd(dict0,sdsnew("0006a"),sdsnew("value6"));
    dictAdd(dict0,sdsnew("0007a"),sdsnew("value7"));
    dictAdd(dict0,sdsnew("0008a"),sdsnew("value8"));

    dictEntry *find = dictFind(dict0, sdsnew("0006a"));
    printf("%s,%s",(char*)find->key,(char*)find->v.val);

    void *privdata[2];
    list *keys = listCreate();
    robj o;
    o.type = OBJ_HASH;
//    o->encoding == OBJ_ENCODING_HT
    privdata[0] = keys;
    privdata[1] = &o;
    server.hz = 10;
    unsigned long v=1;
    while (v != 0) {
        v = dictScan(dict0, v, scanCallbackTest, NULL, privdata);
    }


}
int testRandomLevel(void) {
    int level = 1;
    while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
        level += 1;
    return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}

void scanCallbackTest(void *privdata, const dictEntry *de) {
    void **pd = (void**) privdata;
    list *keys = pd[0];
    robj *o = pd[1];
    robj *key, *val = NULL;

    if (o == NULL) {
        sds sdskey = dictGetKey(de);
        key = createStringObject(sdskey, sdslen(sdskey));
    } else if (o->type == OBJ_SET) {
        sds keysds = dictGetKey(de);
        key = createStringObject(keysds,sdslen(keysds));
    } else if (o->type == OBJ_HASH) {
        sds sdskey = dictGetKey(de);
        sds sdsval = dictGetVal(de);
        key = createStringObject(sdskey,sdslen(sdskey));
        val = createStringObject(sdsval,sdslen(sdsval));
    } else if (o->type == OBJ_ZSET) {
        sds sdskey = dictGetKey(de);
        key = createStringObject(sdskey,sdslen(sdskey));
        val = createStringObjectFromLongDouble(*(double*)dictGetVal(de),0);
    } else {
        serverPanic("Type not handled in SCAN callback.");
    }

    listAddNodeTail(keys, key);
    if (val) listAddNodeTail(keys, val);
}
void* thread_function(void* arg) {

    pthread_mutex_lock(&mutex); // 获取互斥锁
    sleep(10);
    printf(" new thread! Thread ID: %lu\n", (unsigned long)pthread_self());
    pthread_mutex_unlock(&mutex); // 释放互斥锁
    return NULL;
}
void test_thread_mutex(){
    pthread_t tid;
    pthread_create(&tid, NULL, thread_function, NULL);
    printf("Main thread start...\n");
    pthread_mutex_lock(&mutex); // 获取互斥锁
    printf("Main thread processing\n");
    pthread_mutex_unlock(&mutex); // 释放互斥锁

    pthread_join(tid, NULL);
}